📊 جزوه جامع و کامل NumPy

آرایه‌ها، عملیات برداری، توابع آماری و محاسبات عددی در پایتون — به همراه مثال‌های متعدد و توضیحات عمیق

آرایه‌ها و ایجاد داده ایندکس و Slicing عملیات و توابع آماری شکل‌دهی و تخت‌سازی ترکیب و مرتب‌سازی Broadcasting

🧠 NumPy چیست و چرا باید آن را یاد بگیریم؟

NumPy که مخفف Numerical Python است، هستهٔ اصلی محاسبات علمی و تحلیل داده در پایتون محسوب می‌شود. این کتابخانه به ما اجازه می‌دهد تا با آرایه‌های چندبعدی (N-dimensional arrays) کار کنیم و عملیات ریاضی را با سرعت فوق‌العاده بالا انجام دهیم.

اگر به یادگیری ماشین، پردازش تصویر، شبیه‌سازی‌های علمی یا هر حوزه‌ای که با اعداد سروکار دارد علاقه دارید، اولین قدم تسلط بر NumPy است. کتابخانه‌های بزرگی مانند Pandas، TensorFlow، PyTorch، Scikit-learn و SciPy همگی بر پایهٔ NumPy ساخته شده‌اند.

🔥 ویژگی‌های کلیدی NumPy:
• عملیات برداری (Vectorized) بدون نیاز به حلقه
• مصرف حافظه بهینه و سرعت نزدیک به زبان C
• توابع آماری، خطی، مثلثاتی و تصادفی آماده
• قابلیت reshape، index هوشمند و broadcasting

📦 نصب و راه‌اندازی NumPy

برای نصب NumPy کافی است در ترمینال یا command line خود دستور زیر را اجرا کنید:

📦 نصب با pip
pip install numpy

اگر از Jupyter Notebook استفاده می‌کنید، می‌توانید از دستور %pip install numpy استفاده کنید. برای به‌روزرسانی به آخرین نسخه:

🔄 به‌روزرسانی
pip install --upgrade numpy
بررسی نصب موفق: بعد از نصب، در پایتون بنویسید:
import numpy as np
print(np.__version__)
اگر نسخه‌ای مانند 1.26.4 نمایش داده شد، یعنی نصب شما درست است.

📘 آرایه NumPy در مقابل لیست پایتون (مقایسه کامل)

در نگاه اول، آرایه NumPy شبیه لیست پایتون به نظر می‌رسد، اما تفاوت‌های بنیادین و مهمی دارند که در ادامه به تفصیل بررسی می‌کنیم.

✅ ۱. همگنی داده (Homogeneous) در مقابل ناهمگنی (Heterogeneous)

لیست پایتون می‌تواند هر نوع داده‌ای را در کنار هم نگه دارد، اما آرایه NumPy فقط یک نوع داده خاص (مانند int, float, bool) می‌پذیرد. این همگنی باعث می‌شود حافظه به شکل پیوسته و فشرده تخصیص داده شود.

🐍 لیست پایتون
my_list = [10, 'سلام', 3.14, True]  # کاملاً مجاز
🐍 آرایه NumPy
import numpy as np
arr = np.array([10, 20, 30, 40])  # فقط عدد

اگر در آرایه NumPy یک عنصر از نوع متفاوت قرار دهید، کل آرایه به آن نوع تبدیل می‌شود (مثلاً با قراردادن یک عدد اعشاری، کل اعداد صحیح به float تبدیل می‌شوند).

⚡ ۲. سرعت اجرا (چندین برابر سریع‌تر)

به دلیل پیاده‌سازی پایه در زبان C و استفاده از حافظه پیوسته، عملیات روی آرایه‌های NumPy تا ۵۰ برابر سریع‌تر از حلقه‌های پایتون است.

🐍 جمع برداری در NumPy
import numpy as np
a = np.array([1,2,3])
b = np.array([4,5,6])
print(a + b)  # [5 7 9] بدون هیچ حلقه‌ای

💾 ۳. مصرف حافظه

آرایه NumPy حافظه بسیار کمتری مصرف می‌کند. به عنوان مثال، یک آرایه از یک میلیون عدد صحیح در NumPy حدود ۸ مگابایت حافظه اشغال می‌کند، در حالی که لیست پایتون بیش از ۳۰ مگابایت مصرف خواهد داشت.

🧮 ۴. توابع علمی و ریاضی داخلی

NumPy صدها تابع آماده برای محاسبات ماتریسی، آماری، مثلثاتی، نمایی و تصادفی دارد. برای نمونه می‌توان به np.mean()، np.median()، np.std()، np.dot()، np.linalg.inv() اشاره کرد.

📌 نتیجه: اگر با داده‌های عددی کار می‌کنید، همیشه از آرایه NumPy استفاده کنید تا کد شما سریع‌تر، کم‌حجم‌تر و خوانا‌تر شود.

🧩 ایجاد آرایه دوبعدی (ماتریس) در NumPy

برای ساختن آرایه دوبعدی، کافی است از لیست‌های تودرتو استفاده کنیم. هر لیست داخلی یک سطر از ماتریس را مشخص می‌کند.

🐍 ساخت ماتریس ۳×۳
import numpy as np
matrix = np.array([[1, 2, 3],
                   [4, 5, 6],
                   [7, 8, 9]])
print(matrix)

خروجی به شکل زیر خواهد بود:

[[1 2 3]
 [4 5 6]
 [7 8 9]]
💡 نکته: برای دسترسی به عنصر سطر i و ستون j از matrix[i, j] استفاده می‌کنیم. توجه کنید که شماره‌گذاری از صفر شروع می‌شود.

🌈 ساخت آرایه‌های خاص (zeros, ones, full, eye)

گاهی نیاز داریم آرایه‌هایی با مقادیر پیش‌فرض بسازیم. NumPy توابع بسیار مفیدی برای این منظور دارد.

🐍 مثال‌ها
import numpy as np
print('zeros:\n', np.zeros((2,3)))
print('ones:\n', np.ones((2,3)))
print('full:\n', np.full((2,2), 7))
print('eye:\n', np.eye(3))
🔥 کاربرد: در یادگیری ماشین، از np.zeros برای مقداردهی اولیه بایاس‌ها و از np.eye برای کدگذاری one-hot استفاده می‌شود.

🎯 تابع شرطی قدرتمند np.where()

np.where(condition, x, y) مانند یک if-else برداری عمل می‌کند: هر جا شرط درست بود، مقدار x و هر جا نادرست بود، مقدار y قرار می‌گیرد.

🐍 فیلتر کردن اعداد بزرگتر از ۵
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
result = np.where(a > 5, a, 0)
print(result)

خروجی:

[[0 0 0]
 [0 0 6]
 [7 8 9]]

می‌توان از np.where برای جایگزینی مقادیر، پاکسازی داده‌های پرت، یا اعمال شرط‌های پیچیده استفاده کرد.

نکته پیشرفته: اگر فقط آرایه شرط را بدهید، np.where(condition) ایندکس‌هایی که شرط در آن‌ها True است را برمی‌گرداند.

📐 شکل (Shape) و تغییر شکل (Reshape) آرایه

ویژگی .shape ابعاد آرایه را به صورت یک تاپل نمایش می‌دهد. تابع reshape() نیز بدون تغییر داده، شکل آرایه را عوض می‌کند. شرط مهم: تعداد کل عناصر باید ثابت بماند.

🐍 بررسی shape
import numpy as np
a = np.array([[1,2,3],[4,5,6]])
print(a.shape)  # (2, 3)
🐍 تبدیل آرایه ۱۲ عضوی به ۳×۴
b = np.arange(12)
c = b.reshape(3, 4)
print(c)

استفاده از -1 در reshape به NumPy می‌گوید که آن بعد را خودکار محاسبه کند. مثلاً reshape(2, -1) یعنی ۲ سطر و هر تعداد ستون که لازم است.

⚠️ هشدار: reshape() یک view جدید برمی‌گرداند (در صورت امکان) و داده اصلی را کپی نمی‌کند. اگر می‌خواهید کپی مستقل داشته باشید، از .copy() استفاده کنید.

🧩 تخت‌سازی: Flatten() در مقابل Ravel()

برای تبدیل یک آرایه چندبعدی به یک‌بعدی، دو روش اصلی وجود دارد: flatten() و ravel(). تفاوت کلیدی در این است که flatten() همیشه یک کپی جدید از داده می‌سازد، در حالی که ravel() در صورت امکان یک view (نمای بدون کپی) برمی‌گرداند که کارآمدتر است.

ویژگیflatten()ravel()
نوع خروجیهمیشه کپی (copy)view در صورت امکان
سرعتکندتر (به دلیل کپی)بسیار سریع‌تر
مصرف حافظهحافظه اضافیحداقل حافظه
تاثیر روی آرایه اصلیتغییر در خروجی روی اصلی اثر ندارداگر view باشد، تغییر روی اصلی هم اثر می‌کند
🐍 مثال مقایسه
arr = np.array([[1,2,3],[4,5,6]])
print(arr.flatten())
print(arr.ravel())
💡 توصیه: اگر فقط نیاز به خواندن داده به صورت تخت دارید و نمی‌خواهید تغییر دهید، از ravel() استفاده کنید. اگر نیاز به کپی مستقل دارید، flatten() را به کار ببرید.

🧱 ترکیب آرایه‌ها با vstack و hstack

vstack (vertical stack) آرایه‌ها را روی هم (عمودی) قرار می‌دهد. hstack (horizontal stack) آن‌ها را کنار هم (افقی) می‌چسباند.

🐍 مثال vstack و hstack
import numpy as np
a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])
print('vstack:\n', np.vstack((a,b)))
print('hstack:\n', np.hstack((a,b)))

خروجی vstack (۴ سطر، ۲ ستون):

[[1 2]
 [3 4]
 [5 6]
 [7 8]]

خروجی hstack (۲ سطر، ۴ ستون):

[[1 2 5 6]
 [3 4 7 8]]
⚡ در vstack تعداد ستون‌ها باید برابر باشد. در hstack تعداد سطرها باید برابر باشد.

📊 مرتب‌سازی (sort) و ادغام (concatenate)

np.sort() آرایه را مرتب می‌کند و یک کopy مرتب شده برمی‌گرداند (آرایه اصلی تغییر نمی‌کند). np.concatenate() دو یا چند آرایه را در امتداد یک محور به هم می‌چسباند.

🔹 مرتب‌سازی
import numpy as np
arr = np.array([3,1,4,2])
print(np.sort(arr))  # [1 2 3 4]
🔸 concatenate یک بعدی
a = np.array([10,20,30])
b = np.array([40,50])
print(np.concatenate((a,b)))  # [10 20 30 40 50]
برای concatenate دو بعدی می‌توان از axis=0 (عمودی) یا axis=1 (افقی) استفاده کرد.

📊 محاسبات تجمیعی (Aggregation) با توابع آماری

توابع تجمیعی مانند sum(), min(), max(), mean(), std(), var() می‌توانند روی کل آرایه یا روی یک محور خاص اعمال شوند. محور axis=0 به معنای حرکت در راستای سطرها (محاسبه روی ستون‌ها) و axis=1 به معنای حرکت در راستای ستون‌ها (محاسبه روی سطرها) است.

🔹 آمار روی ماتریس
import numpy as np
a = np.array([[1,2,3],[4,5,6]])
print('جمع کل:', a.sum())
print('میانگین ستون‌ها:', a.mean(axis=0))
print('انحراف معیار سطرها:', a.std(axis=1))
📌 کاربرد واقعی: در تحلیل داده، اغلب میانگین و واریانس هر ستون (ویژگی) را محاسبه می‌کنیم تا داده را نرمالیزه کنیم.

📈 تابع linspace: ساخت دنباله خطی با تعداد نقاط مشخص

np.linspace(start, stop, num) آرایه‌ای از اعداد با فاصله مساوی بین start و stop ایجاد می‌کند. برخلاف arange() که بر اساس گام (step) کار می‌کند، linspace دقیقاً تعداد نقاط را کنترل می‌کند.

👩‍💻 مثال
import numpy as np
a = np.linspace(0, 1, 5)
print(a)  # [0.   0.25 0.5  0.75 1.  ]
b = np.linspace(0, 10, 4)
print(b)  # [ 0.          3.33333333  6.66666667 10.        ]
نکته: برای رسم نمودارهای پیوسته، معمولاً از linspace برای تولید محور x و سپس محاسبه y استفاده می‌شود.

📏 ویژگی size و تابع resize

ویژگی .size تعداد کل عناصر آرایه را نشان می‌دهد. اما resize() می‌تواند ابعاد آرایه را تغییر دهد، حتی اگر تعداد عناصر تغییر کند (برخلاف reshape).

👩‍💻 بررسی size و resize
import numpy as np
a = np.array([[1,2,3],[4,5,6]])
print('اندازه:', a.size)   # 6
a.resize(3,4)
print('بعد از resize:\n', a)
⚠️ هشدار: اگر سایز جدید بزرگتر از سایز اصلی باشد، عناصر اضافی به صورت دوره‌ای تکرار می‌شوند. اگر کوچکتر باشد، عناصر اضافی حذف می‌گردند.

🎯 جمع‌بندی نهایی و مسیر ادامه یادگیری

در این جزوه، تمام مفاهیم پایه و پیشرفته NumPy را پوشش دادیم:

🚀 گام بعدی: پس از تسلط بر NumPy، پیشنهاد می‌کنم کتابخانه Pandas را برای کار با داده‌های جدولی و Matplotlib را برای مصورسازی یاد بگیرید. همچنین برای یادگیری ماشین، Scikit-learn منتظر شماست.
✅ کپی شد!